package com.infolab.aims.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.infolab.aims.common.PaginationHelper;
import com.infolab.aims.common.QueryHelper;
import com.infolab.aims.common.bean.SearchCriteria;
import com.infolab.aims.common.bean.SearchResult;
import com.infolab.aims.domain.Vehicle;
import com.infolab.aims.domain.workorder.WorkOrder;
import com.infolab.aims.domain.workorder.WorkOrderAdHoc;
import com.infolab.aims.service.intf.WorkOrderAdHocService;


@Service
@Transactional
public class WorkOrderAdHocServiceImpl implements WorkOrderAdHocService {
	
	Log logger = LogFactory.getLog(getClass());
	@PersistenceContext
	private EntityManager em;
	
	public void createWorkOrderAdHoc(WorkOrderAdHoc workOrderAdHoc)
	{
		WorkOrderAdHoc newWorkOrderAdHoc = new WorkOrderAdHoc();
		
		
		workOrderAdHoc.setModifiedBy(workOrderAdHoc.getCreatedBy());
		workOrderAdHoc.setDateCreated(new Date());
		workOrderAdHoc.setDateModified(new Date());
		
		workOrderAdHoc.setAdHocStatus(WorkOrderAdHoc.ADHOCSTATUS_NEW);
		BeanUtils.copyProperties(workOrderAdHoc,newWorkOrderAdHoc);
		
		em.persist(newWorkOrderAdHoc);
		
		workOrderAdHoc.setWorkOrderAdHocId(newWorkOrderAdHoc.getWorkOrderAdHocId());
		
	}

	public void updateWorkOrderAdHoc(WorkOrderAdHoc workOrderAdHoc) {
		
//		if(workOrderAdHoc.getSection()==null || workOrderAdHoc.getSection().getSectionId()==null)
//			workOrderAdHoc.setSection(null);
		
		WorkOrderAdHoc newWorkOrderAdHoc = em.find(WorkOrderAdHoc.class, workOrderAdHoc.getWorkOrderAdHocId());
		
		workOrderAdHoc.setDateModified(new Date());
		BeanUtils.copyProperties(workOrderAdHoc,newWorkOrderAdHoc);
		
		em.merge(newWorkOrderAdHoc);
	}


	public WorkOrderAdHoc getWorkOrderAdHoc(Integer workOrderAdHocId) {
		
		return em.find(WorkOrderAdHoc.class, workOrderAdHocId);
	}

	public WorkOrderAdHoc findWorkOrderAdHoc(SearchCriteria searchCriteria) {
		
		return null;
	}
	
	public List<WorkOrderAdHoc> findWorkOrderAdHocs(SearchCriteria searchCriteria) {
		
		CriteriaBuilder cb = em.getCriteriaBuilder();
		
		CriteriaQuery<WorkOrderAdHoc> cq = cb.createQuery(WorkOrderAdHoc.class);
		Root<WorkOrderAdHoc> root = cq.from(WorkOrderAdHoc.class);
		
		
		Join<WorkOrderAdHoc,WorkOrder> workOrder = null;
		if (searchCriteria.getSearchCriteria("workOrderId")!= null || searchCriteria.getSearchCriteria("adHocStatusNotCompleted")!= null ) {
			workOrder =
				root.join("workOrder", JoinType.LEFT);	
		}
		
		
		List<Predicate> criteria = new ArrayList<Predicate>();
		
		if (searchCriteria.getSearchCriteria("vehicleId")!= null) {
			ParameterExpression<String> p =
				cb.parameter(String.class, "vehicleId");
				criteria.add(cb.equal(root.get("vehicleId"), p));
		}
		
		
		if (searchCriteria.getSearchCriteria("adHocStatus")!= null) {
			ParameterExpression<String> p =
				cb.parameter(String.class, "adHocStatus");
				criteria.add(cb.equal(root.get("adHocStatus"), p));
		}
		
		if (searchCriteria.getSearchCriteria("adHocStatusNotCompleted")!= null) {
			ParameterExpression<String> p1 =
				cb.parameter(String.class, "adHocStatusNotCompleted");
			ParameterExpression<Integer> p2 =
				cb.parameter(Integer.class, "workOrderId");				
				criteria.add(cb.or(cb.equal(workOrder.get("workOrderId"), p2),cb.notLike(root.<String>get("adHocStatus"), p1)));
		}
		else if (searchCriteria.getSearchCriteria("workOrderId")!= null) {
			ParameterExpression<Integer> p =
				cb.parameter(Integer.class, "workOrderId");
				criteria.add(cb.equal(workOrder.get("workOrderId"), p));
		}
		
		cq.select(root);
		if (criteria.size() == 0) {
			} else if (criteria.size() == 1) {
			cq.where(criteria.get(0));
			} else {
			cq.where(cb.and(criteria.toArray(new Predicate[0])));
		}
		
		TypedQuery<WorkOrderAdHoc> query = em.createQuery(cq);
		
		if (searchCriteria.getSearchCriteria("vehicleId")!= null) {
			query.setParameter("vehicleId", searchCriteria.getSearchCriteria("vehicleId"));
		}
		if (searchCriteria.getSearchCriteria("adHocStatus")!= null) {
			query.setParameter("adHocStatus", searchCriteria.getSearchCriteria("adHocStatus"));
		}
		if (searchCriteria.getSearchCriteria("workOrderId")!= null) {
			query.setParameter("workOrderId", searchCriteria.getSearchCriteria("workOrderId"));
		}
		if (searchCriteria.getSearchCriteria("adHocStatusNotCompleted")!= null) {
			query.setParameter("adHocStatusNotCompleted", searchCriteria.getSearchCriteria("adHocStatusNotCompleted"));
		}
		
		if(searchCriteria.getMaxRow()!=null)
			query.setMaxResults(searchCriteria.getMaxRow());
		
		
		return query.getResultList();
	}

	public SearchResult searchWorkOrderAdHoc(
			SearchCriteria searchCriteria) {
		
		if(searchCriteria.getCurPage()==null)
			searchCriteria.setCurPage(1);
		
		WorkOrderAdHocPaginationHelper helper = new WorkOrderAdHocPaginationHelper();
		
		return helper.getSearchResultFromQueryHelper(em, searchCriteria);
	}
	
	public void deleteWorkOrderAdHoc(Integer id) {
		
		WorkOrderAdHoc workOrderAdHoc = em.getReference(WorkOrderAdHoc.class, id);
		
		em.remove(workOrderAdHoc);
		
	}
	
	public static class WorkOrderAdHocPaginationHelper extends PaginationHelper<WorkOrderAdHoc> {

		@Override
		public String[] getValidColumnName() {
			return new String[]{"appointmentDate","vehicleId","systemCodeValue.systemCodeValueDescription","adHocStatus"};
		}
		
		@Override
		public String[] getValidSortName() {
			return new String[]{"appointmentDate","vehicleId","systemCodeValue.systemCodeValueDescription","adHocStatus"};
		}

		@Override
		public String getDefaultSortName() {
			return "appointmentDate";
		}
		
		@Override
		public QueryHelper getQueryHelper() {
			QueryHelper queryHelper = new QueryHelper();
			queryHelper.select("select workOrderAdHoc from WorkOrderAdHoc workOrderAdHoc");
			return queryHelper;
		}
	}
}
